package c08.executor;

import util.Sleeper;
import lombok.extern.slf4j.Slf4j;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.*;

@Slf4j(topic = "c.TimerTest")
public class TimerTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        testTimer();
//        testScheduledExecutorService();
//        testScheduleAtFixedRate();
//        testScheduleWithFixedDelay();
//        testExecutorServiceException();
//        testExecutorServiceException2();
        testScheduledExecutorServiceException();
    }

    /**
     * 测试在ScheduledExecutorService中处理异常
     */
    private static void testScheduledExecutorServiceException() {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        pool.schedule(() -> {
            try {
                log.debug("task1");
                int i = 1 / 0;
            } catch (Exception e) {
                log.error("error:", e);
            }
        }, 1, TimeUnit.SECONDS);
    }

    /**
     * 在普通线程池中处理异常之 - Future
     */
    private static void testExecutorServiceException2() throws ExecutionException, InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(1);
        Future<Boolean> task1 = pool.submit(() -> {
            log.debug("task1");
            int i = 1 / 0;
            return true;
        });

        log.debug("result: {}", task1.get());
    }

    /**
     * 在普通线程池中处理异常之 - try catch
     */
    private static void testExecutorServiceException() {
        ExecutorService pool = Executors.newFixedThreadPool(1);
        pool.submit(() -> {
            try {
                log.debug("task1");
                int i = 1 / 0;
            } catch (Exception e) {
                log.error("error:", e);
            }
        });
    }

    /**
     * 定时任务之 - scheduleWithFixedDelay
     */
    private static void testScheduleWithFixedDelay() {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        log.debug("start...");
        pool.scheduleWithFixedDelay(() -> {
            log.debug("running...");
        }, 1, 1, TimeUnit.SECONDS);
        // 延时一秒开始执行定时任务，每个任务执行完成后延时一秒再执行下一个任务
    }

    /**
     * 定时任务之 - scheduleAtFixedRate
     */
    private static void testScheduleAtFixedRate() {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        log.debug("start...");
        pool.scheduleAtFixedRate(() -> {
            log.debug("running...");
        }, 1, 1, TimeUnit.SECONDS);
        //
    }

    /**
     * 定时任务之 - ScheduledExecutorService (>=jdk1.5)
     * 可以指定多个线程并行的执行定时任务，某个任务抛出异常不影响其他任务
     */
    private static void testScheduledExecutorService() {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
        pool.schedule(() -> {
            log.debug("task1");
            int i = 1 / 0;
        }, 1, TimeUnit.SECONDS);

        pool.schedule(() -> {
            log.debug("task2");
        }, 1, TimeUnit.SECONDS);
    }

    /**
     * 定时任务之 - Timer (>=jdk1.3)
     * Timer始终使用一个线程串行执行任务，当某个任务抛出异常，则其后面的任务都不会执行，线程被迫终止
     */
    private static void testTimer() {
        Timer timer = new Timer();
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 1");
                Sleeper.sleep(2);
            }
        };
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {
                log.debug("task 2");
            }
        };

        log.debug("start...");
        timer.schedule(task1, 1000);
        timer.schedule(task2, 1000);
    }
}
